package com.yu.yupicture.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yu.yupicture.Untils.ThrowUntil;
import com.yu.yupicture.exception.ErrorCode;
import com.yu.yupicture.exception.biusnessException;
import com.yu.yupicture.model.domain.dto.spaceAnalyze.*;
import com.yu.yupicture.model.domain.entry.Picture;
import com.yu.yupicture.model.domain.entry.Space;
import com.yu.yupicture.model.domain.entry.User;
import com.yu.yupicture.model.domain.vo.spaceAnalyze.*;
import com.yu.yupicture.service.PictureService;
import com.yu.yupicture.service.SpaceAnalyze;
import com.yu.yupicture.service.SpaceService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;


@Service
@RequiredArgsConstructor
public class spaceAnalyzeImpl implements SpaceAnalyze {


    private final PictureService pictureService;
    private final SpaceService spaceService;


    /**
     * 空间资源使用情况分析
     *
     * @param spaceAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public SpaceUsageAnalyzeResponse spaceUsageAnalyze(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        Long spaceId = spaceAnalyzeRequest.getSpaceId();
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();

        //1：权限校验
        this.checkSpaceAnalyze(spaceAnalyzeRequest, loginUser);
        SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
        //判断个人空间还是私人空间
        if (queryAll || queryPublic) {
            //2：获取查询条件
            QueryWrapper<Picture> spaceQueryWrapper = this.getSpaceQueryWrapper(spaceAnalyzeRequest);
            spaceQueryWrapper.select("picSize");
            List<Object> pictureList = pictureService.getBaseMapper().selectObjs(spaceQueryWrapper);
            if (pictureList == null) {
                throw new biusnessException(ErrorCode.NOT_FOUND_ERROR);
            }
            //获得当前图片数量
            long totalCount = pictureList.size();
            //获取当前图片大小
            long totalSize = pictureList.stream().mapToLong(pic -> pic instanceof Long ? (Long) pic : 0).sum();

            //封装结果
            spaceUsageAnalyzeResponse.setUsedCount(totalCount);
            spaceUsageAnalyzeResponse.setUsedSize(totalSize);
            spaceUsageAnalyzeResponse.setMaxSize(null);
            spaceUsageAnalyzeResponse.setSizeUsageRatio(null);
            spaceUsageAnalyzeResponse.setMaxCount(null);
            spaceUsageAnalyzeResponse.setCountUsageRatio(null);
        } else {
            //查询
            Space space = spaceService.getBaseMapper().selectOne(new QueryWrapper<Space>().eq("id", spaceId));
            //封装结果
            Long maxSize = space.getMaxSize();
            Long maxCount = space.getMaxCount();
            Long totalSize = space.getTotalSize();
            Long totalCount = space.getTotalCount();

            //计算使用比例
            double sizeUsageRatio = NumberUtil.round((double) (totalSize * 100) / maxSize, 2).doubleValue();
            double countUsageRatio = NumberUtil.round((double) (totalCount * 100) / maxCount, 2).doubleValue();

            spaceUsageAnalyzeResponse.setUsedSize(totalSize);
            spaceUsageAnalyzeResponse.setMaxSize(maxSize);
            spaceUsageAnalyzeResponse.setSizeUsageRatio(sizeUsageRatio);
            spaceUsageAnalyzeResponse.setUsedCount(totalCount);
            spaceUsageAnalyzeResponse.setMaxCount(maxCount);
            spaceUsageAnalyzeResponse.setCountUsageRatio(countUsageRatio);
        }
        return spaceUsageAnalyzeResponse;
    }

    /**
     * 空间分类使用情况分析
     *
     * @param spaceAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceCategoryAnalyzeResponse> spaceCategoryAnalyze(SpaceCategoryAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        Long spaceId = spaceAnalyzeRequest.getSpaceId();
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();

        //1：权限校验
        this.checkSpaceAnalyze(spaceAnalyzeRequest, loginUser);
        //2:获得查询条件
        QueryWrapper<Picture> QueryWrapper = this.getSpaceQueryWrapper(spaceAnalyzeRequest);

        //3：查询
        QueryWrapper.select("category As category", "count(*) As count", "sum(picSize) As totalSize").groupBy("category");

        return pictureService.getBaseMapper().selectMaps(QueryWrapper)
                .stream().map(map -> {
                    SpaceCategoryAnalyzeResponse spaceCategoryAnalyzeResponse = new SpaceCategoryAnalyzeResponse();
                    spaceCategoryAnalyzeResponse.setCategory(map.get("category") == null ? "未分类" : map.get("category").toString());
                    spaceCategoryAnalyzeResponse.setCount(map.get("count") == null ? 0 : Long.parseLong(map.get("count").toString()));
                    spaceCategoryAnalyzeResponse.setTotalSize(map.get("totalSize") == null ? 0 : Long.parseLong(map.get("totalSize").toString()));
                    return spaceCategoryAnalyzeResponse;
                }).toList();
    }

    /**
     * 空间标签使用情况分析
     *
     * @param spaceTagAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceTagAnalyzeResponse> spaceTagAnalyze(SpaceTagAnalyzeRequest spaceTagAnalyzeRequest, User loginUser) {
        //1；权限校验
        this.checkSpaceAnalyze(spaceTagAnalyzeRequest, loginUser);
        //2：获取查询条件
        QueryWrapper<Picture> queryWrapper = this.getSpaceQueryWrapper(spaceTagAnalyzeRequest);

        //查询符合条件的tags
        queryWrapper.select("tags");
        List<String> list = pictureService.getBaseMapper().selectObjs(queryWrapper);

        Map<String, Long> map = list.stream().filter(Objects::nonNull)
                .flatMap(obj -> JSONUtil.toList(obj, String.class).stream())
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));

        //4：封装结果
        return map.entrySet().stream()
                .sorted((e1, e2) -> Long.compare(e2.getValue(), e1.getValue()))
                .map(entry ->
                        new SpaceTagAnalyzeResponse(entry.getKey(), entry.getValue())).collect(Collectors.toList());
    }

    /**
     * 空间图片大小使用情况分析
     *
     * @param spaceSizeAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceSizeAnalyzeResponse> spaceSizeAnalyze(SpaceSizeAnalyzeRequest spaceSizeAnalyzeRequest, User loginUser) {
        //1；权限校验
        this.checkSpaceAnalyze(spaceSizeAnalyzeRequest, loginUser);
        //2：获取查询条件
        QueryWrapper<Picture> queryWrapper = this.getSpaceQueryWrapper(spaceSizeAnalyzeRequest);

        //查询符合条件的图片大小
        queryWrapper.select("picSize");
        List<Long> picSizes = pictureService.getBaseMapper().selectObjs(queryWrapper);

        // 定义分段范围，注意使用有序 Map
        Map<String, Long> sizeRanges = new LinkedHashMap<>();
        sizeRanges.put("<100KB", picSizes.stream().filter(Objects::nonNull).filter(size -> size < 100 * 1024).count());
        sizeRanges.put("100KB-500KB", picSizes.stream().filter(Objects::nonNull).filter(size -> size >= 100 * 1024 && size < 500 * 1024).count());
        sizeRanges.put("500KB-1MB", picSizes.stream().filter(Objects::nonNull).filter(size -> size >= 500 * 1024 && size < 1 * 1024 * 1024).count());
        sizeRanges.put(">1MB", picSizes.stream().filter(Objects::nonNull).filter(size -> size >= 1 * 1024 * 1024).count());

        return sizeRanges.entrySet().stream()
                .map(entry -> new SpaceSizeAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    /**
     * 用户上传情况分析
     *
     * @param spaceAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<SpaceUserAnalyzeResponse> userUploadAnalyze(SpaceUserAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        //1；权限校验
        this.checkSpaceAnalyze(spaceAnalyzeRequest, loginUser);
        //2：获取查询条件
        QueryWrapper<Picture> queryWrapper = this.getSpaceQueryWrapper(spaceAnalyzeRequest);
        //判断是否查询指定用户上传
        Long userId = spaceAnalyzeRequest.getUserId();
        queryWrapper.eq(ObjUtil.isNotNull(userId), "userId", userId);
        //判断时间维度
        String timeDimension = spaceAnalyzeRequest.getTimeDimension();

        switch (timeDimension) {
            case "day" -> {
                queryWrapper.select("date_format(createTime, '%Y-%m-%d') AS period", "count(*) AS count");
            }
            case "week" -> {
                queryWrapper.select("YEARWEEK(createTime) AS period", "count(*) AS count");
            }
            case "month" -> {
                queryWrapper.select("date_format(createTime, '%Y-%m') AS period", "count(*) AS count");
            }
            default -> throw new biusnessException(ErrorCode.PARAMS_ERROR, "时间维度错误");
        }
        //排序
        queryWrapper.groupBy("period").orderByAsc("period");
        List<Map<String, Object>> maps = pictureService.getBaseMapper().selectMaps(queryWrapper);
        return maps.stream().map(map -> {
            return new SpaceUserAnalyzeResponse(map.get("period").toString(), Long.parseLong(map.get("count").toString()));
        }).toList();
    }

    /**
     * 空间使用情况排名
     * @param spaceRankAnalyzeRequest
     * @param loginUser
     * @return
     */
    @Override
    public List<Space> spaceUsageRank(SpaceRankAnalyzeRequest spaceRankAnalyzeRequest, User loginUser) {
        if (!pictureService.isAdmin(loginUser)){
            throw new biusnessException(ErrorCode.NO_AUTH_ERROR);
        }
        Integer topN = spaceRankAnalyzeRequest.getTopN();
        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "spaceName", "totalSize", "userId").last(" order by totalSize desc limit " + topN );
        return spaceService.getBaseMapper().selectList(queryWrapper);
    }

    /**
     * 获取空间查询条件
     *
     * @param spaceAnalyzeRequest
     * @return
     */
    @Override
    public QueryWrapper<Picture> getSpaceQueryWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest) {
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        Long spaceId = spaceAnalyzeRequest.getSpaceId();
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();

        if (queryPublic) {
            queryWrapper.isNull("spaceId");
        } else if (spaceId != null) {
            queryWrapper.eq("spaceId", spaceId);
        }

        return queryWrapper;
    }

    /**
     * 权限校验
     *
     * @param spaceAnalyzeRequest
     * @param loginUser
     */
    @Override
    public void checkSpaceAnalyze(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        Long spaceId = spaceAnalyzeRequest.getSpaceId();
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();

        if (queryAll || queryPublic) {
            ThrowUntil.throwIf(!pictureService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR);
        } else if (spaceId != null) {
            Space space = spaceService.getById(spaceId);
            ThrowUntil.throwIf(space == null, ErrorCode.NO_AUTH_ERROR, "空间不存在");
            ThrowUntil.throwIf(!space.getUserId().equals(loginUser.getId()) || !pictureService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR);
        }
    }


}
